package com.ctshk.rpc.goods.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.GlobalConstants;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.goods.dto.FreightTemplateDTO;
import com.ctshk.rpc.goods.dto.RegionalFreightDTO;
import com.ctshk.rpc.goods.entity.FreightTemplate;
import com.ctshk.rpc.goods.entity.RegionalFreight;
import com.ctshk.rpc.goods.mapper.FreightTemplateMapper;
import com.ctshk.rpc.goods.mapper.RegionalFreightMapper;
import com.ctshk.rpc.goods.req.FreightTemplateAddReq;
import com.ctshk.rpc.goods.req.FreightTemplatePageReq;
import com.ctshk.rpc.goods.req.RegionalFreightAddReq;
import com.ctshk.rpc.goods.service.IFreightTemplateService;
import com.ctshk.rpc.system.service.ISysPermissionService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 运费模板表 服务实现类
 * </p>
 *
 * @author 姜斌文
 * @since 2021-04-09
 */
@DubboService
public class FreightTemplateServiceImpl extends ServiceImpl<FreightTemplateMapper, FreightTemplate> implements IFreightTemplateService {

	@Autowired
	private FreightTemplateMapper templateMapper;
	
	@Autowired
	private RegionalFreightMapper freightMapper;

	@Autowired
	private RegionalFreightMapper regionalFreightMapper;

	@DubboReference
	private ISysPermissionService sysPermissionService;

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void addFreightTemplate(FreightTemplateAddReq addReq, Long userId)
			throws Exception {
		FreightTemplate template = new FreightTemplate();
        BeanUtils.copyProperties(addReq, template, EntityUtil.getNullPropertyNames(addReq));
        List<RegionalFreightAddReq> freightAddReqs = addReq.getRegionalFreightAddReqList();
        checkAddParamData(freightAddReqs, template); // 数据校验
		LocalDateTime now=LocalDateTime.now();
		template.setId(SnowflakeIdWorker.nextId());
		template.setCreateId(userId);
		template.setGmtCreate(now);
		template.setModifiedId(userId);
		template.setGmtModified(now);
		template.setIsDeleted(IsDeletedCode.NO.getCode());
		templateMapper.insert(template);
        List<RegionalFreight> freightList = new ArrayList<RegionalFreight>();
        freightAddReqs.stream().forEach(freightReq -> {
        	RegionalFreight freight = new RegionalFreight();
            BeanUtils.copyProperties(freightReq, freight, EntityUtil.getNullPropertyNames(freightReq));
            freight.setTemplateId(template.getId());
    		freight.setCreateId(userId);
    		freight.setGmtCreate(now);
    		freight.setModifiedId(userId);
    		freight.setGmtModified(now);
    		freight.setIsDeleted(IsDeletedCode.NO.getCode());
            freightList.add(freight);
        });
		freightMapper.insertBatchSomeColumn(freightList);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void updateFreightTemplate(FreightTemplateAddReq addReq, Long userId) {
		FreightTemplate template = templateMapper.selectById(addReq.getId());
		List<RegionalFreightAddReq> freightAddReqs = addReq.getRegionalFreightAddReqList();
		List<FreightTemplateDTO> templateName = templateMapper.findTemplateNameList(template.getTemplateName());
		if(templateName.size() > 1) {
			// 进行更新时只需要检查是否只有一个即可
			throw new BusinessException(SystemError.MALL_MERCHANDISE_23008);
		}
        BeanUtils.copyProperties(addReq, template, EntityUtil.getNullPropertyNames(addReq));
		LocalDateTime now=LocalDateTime.now();
		template.setModifiedId(userId);
		template.setGmtModified(now);
		templateMapper.updateById(template);
		List<RegionalFreight> dbFreightList = freightMapper.findBatchFreightByTemplateId(template.getId());
        List<RegionalFreight> freightList = new ArrayList<RegionalFreight>();
        freightAddReqs.stream().forEach(freightReq -> {
			RegionalFreight freight = new RegionalFreight();
			BeanUtils.copyProperties(freightReq, freight, EntityUtil.getNullPropertyNames(freightReq));
			freight.setTemplateId(template.getId());
			if (null == freight.getId()) {
				freight.setCreateId(userId);
				freight.setGmtCreate(now);
			}
			freight.setModifiedId(userId);
			freight.setGmtModified(now);
			freight.setIsDeleted(IsDeletedCode.NO.getCode());
			freightList.add(freight);
        });
        
        if (null == dbFreightList || dbFreightList.size() == 0) {
    		freightMapper.insertBatchSomeColumn(freightList);
    		return;
		}
        // 比对DB中的运费信息与当前操作的运费进行比较，进行更新或新增数据进行存储
        List<RegionalFreight> newFreight = new ArrayList<RegionalFreight>();
        List<RegionalFreight> upFreight = new ArrayList<RegionalFreight>();
        for (RegionalFreight currentFreight : freightList) {
        	if (null == currentFreight.getId()) {
        		newFreight.add(currentFreight);
        		continue;
			}
			for (RegionalFreight dbFreight : dbFreightList) {
				if (dbFreight.getId().longValue() == currentFreight.getId().longValue()) {
		            BeanUtils.copyProperties(currentFreight, dbFreight, EntityUtil.getNullPropertyNames(currentFreight));
		            dbFreight.setModifiedId(userId);
		            dbFreight.setGmtModified(now);
		            dbFreight.setIsDeleted(IsDeletedCode.NO.getCode());
		            upFreight.add(dbFreight);
		            dbFreightList.remove(dbFreight);
					break;
				}
			}
		}
        // 对DB进行更新或新增操作
        if (dbFreightList.size() > 0) {
        	// 軟刪除
        	dbFreightList.stream().forEach(delFreight ->{
        		delFreight.setIsDeleted(IsDeletedCode.YES.getCode());
        		delFreight.setModifiedId(userId);
        		delFreight.setGmtModified(now);
        		upFreight.add(delFreight);
        	});
    		// 硬刪除：如果要硬刪除,開放此句代碼,屏蔽軟刪除代碼行。
    		//freightMapper.deleteBatchIds(dbFreightList); 
		}
        if (null != newFreight && newFreight.size() > 0) {
        	freightMapper.insertBatchSomeColumn(newFreight);
		}
        if (null != upFreight && upFreight.size() > 0) {
        	for (RegionalFreight regionalFreight : upFreight) {
        		freightMapper.updateById(regionalFreight);
			}
		}
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void deleteFreightTemplate(FreightTemplateAddReq delReq, Long userId)
			throws Exception {
		FreightTemplate template = templateMapper.selectById(delReq.getId());
		LocalDateTime now=LocalDateTime.now();
		template.setModifiedId(userId);
		template.setGmtModified(now);
		template.setIsDeleted(IsDeletedCode.YES.getCode());
		templateMapper.updateById(template);
		
		List<RegionalFreight> freightList = freightMapper.findBatchFreightByTemplateId(template.getId());
		freightList.stream().forEach(freight ->{
			freight.setModifiedId(userId);
			freight.setGmtModified(now);
			freight.setIsDeleted(IsDeletedCode.YES.getCode());
			freightMapper.updateById(freight);
		});
	}

	public PageResponse<FreightTemplateDTO> findFreightTemplate(FreightTemplatePageReq pageReq, TokenUser tokenUser) {
		Result<List<Long>> permissionResult = sysPermissionService.queryPermission(pageReq.getMenuId(), tokenUser.getId());
		if (!permissionResult.isSuccess()) {
			SystemError result = SystemError.getDefined(permissionResult.getCode());
			throw new BusinessException(result);
		}
		//不是管理员
		if (!GlobalConstants.Role.isAdmin(tokenUser.getUsername())) {
			pageReq.setIsNotAdmin(1);
			String ids = "";
			List<Long> data = permissionResult.getData();
			if(data != null && data.size() >0){
				for (Long datum : data) {
					ids += datum + ",";
				}
			}
			if(ids.length() > 0){
				ids = ids.substring(0, ids.length() - 1);
			}
			pageReq.setUserIds(ids);
		}

		IPage<FreightTemplateDTO> page = new Page<FreightTemplateDTO>(pageReq.getPageNo(),pageReq.getPageSize());
		IPage<FreightTemplateDTO> iPage = templateMapper.findFreightTemplateByAll(page, pageReq);
		List<FreightTemplateDTO> templateList = iPage.getRecords();
		List<FreightTemplateDTO> pageDTOList = EntityUtil.copyList(templateList, FreightTemplateDTO.class);
		return new PageResponse<>(pageDTOList, iPage.getCurrent() == 1,
				iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()),
				iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
	}

	@Override
	public List<FreightTemplateDTO> findClassificationTemplateList() {
		List<FreightTemplateDTO> result = templateMapper.findTemplateName();
		return result;
	}

	@Override
	public JSONObject getFreightByWeightOrPieceCount(Long id, List<Double> firstArticles, Long regionId) {
		JSONObject info = new JSONObject();
		info.put("error", "");
		info.put("frachtpreis", "");
		try {
			FreightTemplate dbFreightTemplate = templateMapper.selectTemplateById(id);
			if(dbFreightTemplate != null && dbFreightTemplate.getCashOnDelivery() == 2){
				// 货到付款返回价格0元
				info.put("frachtpreis", 0);
				return info;
			}
			if (dbFreightTemplate == null) {
				throw new BusinessException(SystemError.MALL_MERCHANDISE_23004);
			}
			if (dbFreightTemplate.getPricingMethod() == null) {
				throw new BusinessException(SystemError.MALL_MERCHANDISE_23005);
			}
			List<RegionalFreight> dbRegionalFreight = freightMapper.findBatchFreightByTemplateId(dbFreightTemplate.getId());
			boolean validRegional = false;
			for (RegionalFreight regionalFreight:dbRegionalFreight) {
//				if (regionalFreight.getRegionId().longValue() == regionId.longValue()) {
				if (regionalFreight != null && regionalFreight.getRegionIdAndNameJsonList() != null) { // 需要完善此处的区域信息
					if(regionalFreight.getRegionIdAndNameJsonList().toString().contains(regionId.toString())){
						validRegional = true;
						if (dbFreightTemplate.getPricingMethod().intValue() == 1){ // 計重方式
							Double firstArticleSum = 0.0;
							BigDecimal freightAmount = new BigDecimal(0);
							for (Double firstArticle:firstArticles) {
								firstArticleSum += firstArticle;
							}
							if (regionalFreight.getFirstArticle() < firstArticleSum){ // 第一次比對為首重
								firstArticleSum = firstArticleSum - regionalFreight.getFirstArticle();
								freightAmount = freightAmount.add(regionalFreight.getFreightAmount());
							} else {
								freightAmount = freightAmount.add(regionalFreight.getFreightAmount());
								info.put("frachtpreis", freightAmount);
								return info;
							}

							do {
								firstArticleSum = firstArticleSum - regionalFreight.getContinuation();
								freightAmount = freightAmount.add(regionalFreight.getRenewAmount());
							}while (firstArticleSum >= regionalFreight.getContinuation());
							info.put("frachtpreis", freightAmount);
							return info;
						} else { // 計件方式
							BigDecimal freightAmount = new BigDecimal(0);
							Double continuationCount = 1.0;
							for (int i = 0; i < firstArticles.size(); i++){
								if (i == 0) {
									freightAmount = freightAmount.add(regionalFreight.getFreightAmount());
									continue;
								}
								if (regionalFreight.getContinuation() < continuationCount) {
									continuationCount += 1;
									if (firstArticles.size() == i+1){ // 如果為最後一個，並且多餘件數，按續重算
										freightAmount = freightAmount.add(regionalFreight.getRenewAmount());
									}
								} else {
									freightAmount = freightAmount.add(regionalFreight.getRenewAmount());
									continuationCount = 1.0;
								}

							}
							info.put("frachtpreis", freightAmount);
							return info;
						}
					}
				}else{
					validRegional = true;
					if (dbFreightTemplate.getPricingMethod().intValue() == 1){ // 計重方式
						Double firstArticleSum = 0.0;
						BigDecimal freightAmount = new BigDecimal(0);
						for (Double firstArticle:firstArticles) {
							firstArticleSum += firstArticle;
						}
						if (regionalFreight.getFirstArticle() < firstArticleSum){ // 第一次比對為首重
							firstArticleSum = firstArticleSum - regionalFreight.getFirstArticle();
							freightAmount = freightAmount.add(regionalFreight.getFreightAmount());
						} else {
							freightAmount = freightAmount.add(regionalFreight.getFreightAmount());
							info.put("frachtpreis", freightAmount);
							return info;
						}

						do {
							firstArticleSum = firstArticleSum - regionalFreight.getContinuation();
							freightAmount = freightAmount.add(regionalFreight.getRenewAmount());
						}while (firstArticleSum >= regionalFreight.getContinuation());
						info.put("frachtpreis", freightAmount);
						return info;
					} else { // 計件方式
						BigDecimal freightAmount = new BigDecimal(0);
						Double continuationCount = 1.0;
						for (int i = 0; i < firstArticles.size(); i++){
							if (i == 0) {
								freightAmount = freightAmount.add(regionalFreight.getFreightAmount());
								continue;
							}
							if (regionalFreight.getContinuation() < continuationCount) {
								continuationCount += 1;
								if (firstArticles.size() == i+1){ // 如果為最後一個，並且多餘件數，按續重算
									freightAmount = freightAmount.add(regionalFreight.getRenewAmount());
								}
							} else {
								freightAmount = freightAmount.add(regionalFreight.getRenewAmount());
								continuationCount = 1.0;
							}

						}
						info.put("frachtpreis", freightAmount);
						return info;
					}
				}
			}
			if (!validRegional){
				throw new BusinessException(SystemError.MALL_MERCHANDISE_23006);
			}
		} catch (Exception e){
			info.put("error", e.getMessage());
			return info;
		}
		return info;
	}

	@Override
	public FreightTemplateDTO findFrightTemplateInfoById(Long id) {
		FreightTemplate dbFreightTemplate = templateMapper.selectTemplateById(id);
		if (dbFreightTemplate == null) {
			throw new BusinessException(SystemError.MALL_MERCHANDISE_23004);
		}
		if (dbFreightTemplate.getPricingMethod() == null) {
			throw new BusinessException(SystemError.MALL_MERCHANDISE_23005);
		}
		FreightTemplateDTO freightTemplateDTO = new FreightTemplateDTO();
		BeanUtils.copyProperties(dbFreightTemplate, freightTemplateDTO);
		List<RegionalFreight> regionalFreights = regionalFreightMapper.findBatchFreightByTemplateId(freightTemplateDTO.getId());
		if(regionalFreights != null && regionalFreights.size() > 0){
			List<RegionalFreightDTO> regionalFreightDTOS = new ArrayList<>();
			regionalFreights.stream().forEach(item -> {
				RegionalFreightDTO regionalFreightDTO = new RegionalFreightDTO();
				BeanUtils.copyProperties(item, regionalFreightDTO);
				regionalFreightDTOS.add(regionalFreightDTO);
			});
			freightTemplateDTO.setRegionalFreightDTOS(regionalFreightDTOS);
			return freightTemplateDTO;
		}
		throw new BusinessException(SystemError.MALL_MERCHANDISE_23004);
	}


	private void checkAddParamData(List<RegionalFreightAddReq> freightAddReqs,FreightTemplate template) throws Exception {
		if (null == template.getTemplateName() || template.getTemplateName().length() == 0) {
			throw new BusinessException(SystemError.SYS_402);
		}
		if (template.getTemplateName().length() > 24) {
			throw new BusinessException(SystemError.MALL_MERCHANDISE_23007);
		}
		if (null == freightAddReqs || freightAddReqs.size() == 0) {
			throw new BusinessException(SystemError.SYS_402);
		}

		List<FreightTemplateDTO> templateName = templateMapper.findTemplateNameList(template.getTemplateName());
		if(templateName.size() > 0){
			if(null == template.getId()){
				throw new BusinessException(SystemError.MALL_MERCHANDISE_23008);
			} else {
				for (FreightTemplateDTO freightTemplateDTO : templateName) {
					if(freightTemplateDTO.getTemplateName().equals(template.getTemplateName()))
						throw new BusinessException(SystemError.MALL_MERCHANDISE_23008);
					}
				}
			}
		}


//        List<FreightTemplateDTO> TemplateNames = templateMapper.findTemplateName();
//		Map<String, Long> map = TemplateNames.stream().collect(Collectors.toMap(FreightTemplateDTO::getTemplateName, FreightTemplateDTO::getId));
//		if (map.containsKey(template.getTemplateName())) {
//			if(null == template.getId()){
//				throw new BusinessException(SystemError.MALL_MERCHANDISE_23008);
//			} else {
//				Long key = map.get(template.getTemplateName());
//				if (key.longValue() != template.getId().longValue()) {
//					throw new BusinessException(SystemError.MALL_MERCHANDISE_23008);
//				}
//			}
//		}
}
